namespace C4F.DevKit.Bluetooth.ObjectExchange
{
    #region Using Directives
    using System;
    using C4F.DevKit.Bluetooth.ObjectExchange.Resources;
    #endregion

    /// <summary>
    /// Contains functions for formatting values as required during 
    /// ObjectExchange.
    /// </summary>
    public static class ObjectExchangeHelper
    {
        #region Public Static Functions

        /// <summary>
        /// If the ushort value passed has Little Endian encoding, the function
        /// returns a ushort value with Big Endian encoding.
        /// Similarly, if the ushort value passed has Big Endian encoding, the
        /// function returns a ushort value with Little Endian encoding.
        /// </summary>
        /// <param name="value">Ushort value to be operated on.</param>
        /// <returns>Formatted ushort value.</returns>
        public static ushort FormatUInt16(ushort value)
        {
            if (BitConverter.IsLittleEndian)
                return Convert.ToUInt16((int)((value >> 8) |
                                              ((value << 8) & 0xffff)));
            else
                return value;
        }

        /// <summary>
        /// If the uint value passed has Little Endian encoding, the function
        /// returns a uint value with Big Endian encoding.
        /// Similarly, if the uint value passed has Big Endian encoding, the
        /// function returns a uint value with Little Endian encoding.
        /// </summary>
        /// <param name="value">Uint value to be operated on.</param>
        /// <returns>Formatted uint value.</returns>
        public static uint FormatUInt32(uint value)
        {
            if (BitConverter.IsLittleEndian)
                return ((((value << 0x18) & 0xff000000) |
                         ((value << 8) & 0xff0000)) |
                        ((value >> 8) & 0xff00))
                       | ((value >> 0x18) & 0xff);
            else
                return value;
        }

        /// <summary>
        /// Throws an ObjectExchangeException depending on the specified opcode.
        /// </summary>
        /// <param name="opcode">An ObjectExchange opcode based on which the 
        /// exception has to be generated and thrown.</param>
        /// <exception cref="ObjectExchangeException">An ObjectExchangeException
        /// with the ErrorType set appropriately depending on the specified 
        /// opcode is raised.</exception>
        public static void RaiseObjectExchangeError(ObjectExchangeOpcode opcode)
        {
            // Take action based on the response sent by the Object Exchange 
            // Service.
            switch (opcode)
            {
                case ObjectExchangeOpcode.Forbidden:
                case ObjectExchangeOpcode.ForbiddenFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.Forbidden,
                        ObjectExchangeResources.Error_Forbidden);

                case ObjectExchangeOpcode.NotFound:
                case ObjectExchangeOpcode.NotFoundFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.NotFound,
                        ObjectExchangeResources.Error_NotFound);

                case ObjectExchangeOpcode.Conflict:
                case ObjectExchangeOpcode.ConflictFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.Conflict,
                        ObjectExchangeResources.Error_Conflict);

                case ObjectExchangeOpcode.Unauthorized:
                case ObjectExchangeOpcode.UnauthorizedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.SecurityError,
                        ObjectExchangeResources.Error_Unauthorized);

                case ObjectExchangeOpcode.NotAcceptable:
                case ObjectExchangeOpcode.NotAcceptableFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.NotAcceptable,
                        ObjectExchangeResources.Error_NotAcceptable);

                case ObjectExchangeOpcode.InternalServerError:
                case ObjectExchangeOpcode.InternalServerErrorFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.InternalServerError,
                        ObjectExchangeResources.Error_InternalServerError);

                case ObjectExchangeOpcode.ServiceUnavailable:
                case ObjectExchangeOpcode.ServiceUnavailableFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.ServiceUnavailable,
                        ObjectExchangeResources.Error_ServiceUnavailable);

                case ObjectExchangeOpcode.BadRequest:
                case ObjectExchangeOpcode.BadRequestFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.BadRequest,
                        ObjectExchangeResources.Error_BadRequest);

                case ObjectExchangeOpcode.MethodNotAllowed:
                case ObjectExchangeOpcode.MethodNotAllowedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.MethodNotAllowed,
                        ObjectExchangeResources.Error_MethodNotAllowed);

                case ObjectExchangeOpcode.NotModified:
                case ObjectExchangeOpcode.NotModifiedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.NotModified,
                        ObjectExchangeResources.Error_NotModified);

                case ObjectExchangeOpcode.NotImplemented:
                case ObjectExchangeOpcode.NotImplementedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.NotImplemented,
                        ObjectExchangeResources.Error_NotImplemented);

                case ObjectExchangeOpcode.RequestTimeOut:
                case ObjectExchangeOpcode.RequestTimeOutFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.Timeout,
                        ObjectExchangeResources.Error_RequestTimeOut);

                case ObjectExchangeOpcode.MovedPermanently:
                case ObjectExchangeOpcode.MovedPermanentlyFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.ResourceMoved,
                        ObjectExchangeResources.Error_MovedPermanently);

                case ObjectExchangeOpcode.MovedTemporarily:
                case ObjectExchangeOpcode.MovedTemporarilyFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.ResourceMoved,
                        ObjectExchangeResources.Error_MovedTemporarily);

                case ObjectExchangeOpcode.SeeOther:
                case ObjectExchangeOpcode.SeeOtherFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.ResourceMoved,
                        ObjectExchangeResources.Error_SeeOther);

                case ObjectExchangeOpcode.UseProxy:
                case ObjectExchangeOpcode.UseProxyFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.SecurityError,
                        ObjectExchangeResources.Error_UseProxy);

                case ObjectExchangeOpcode.ProxyAuthenticationRequired:
                case ObjectExchangeOpcode.ProxyAuthenticationRequiredFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.SecurityError,
                        ObjectExchangeResources.Error_ProxyAuthRequired);

                case ObjectExchangeOpcode.Gone:
                case ObjectExchangeOpcode.GoneFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.NotFound,
                        ObjectExchangeResources.Error_Gone);

                case ObjectExchangeOpcode.LengthRequired:
                case ObjectExchangeOpcode.LengthRequiredFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.AdditionalInfoRequired,
                        ObjectExchangeResources.Error_LengthRequired);

                case ObjectExchangeOpcode.PreconditionFailed:
                case ObjectExchangeOpcode.PreconditionFailedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.AdditionalInfoRequired,
                        ObjectExchangeResources.Error_PreconditionFailed);

                case ObjectExchangeOpcode.UnsupportedMediaType:
                case ObjectExchangeOpcode.UnsupportedMediaTypeFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.UnsupportedMediaType,
                        ObjectExchangeResources.Error_UnsupportedMediaType);

                case ObjectExchangeOpcode.RequestedEntityTooLarge:
                case ObjectExchangeOpcode.RequestedEntityTooLargeFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.RequestedEntityTooLarge,
                        ObjectExchangeResources.Error_RequestedEntityTooLarge);

                case ObjectExchangeOpcode.RequestUrlTooLarge:
                case ObjectExchangeOpcode.RequestUrlTooLargeFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.RequestUrlTooLarge,
                        ObjectExchangeResources.Error_RequestedUrlTooLarge);

                case ObjectExchangeOpcode.BadGateway:
                case ObjectExchangeOpcode.BadGatewayFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.GatewayError,
                        ObjectExchangeResources.Error_BadGateway);

                case ObjectExchangeOpcode.GatewayTimeout:
                case ObjectExchangeOpcode.GatewayTimeoutFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.GatewayError,
                        ObjectExchangeResources.Error_GatewayTimeout);

                case ObjectExchangeOpcode.HttpVersionNotSupported:
                case ObjectExchangeOpcode.HttpVersionNotSupportedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.NotAcceptable,
                        ObjectExchangeResources.Error_HttpVersionNotSupported);

                case ObjectExchangeOpcode.DatabaseFull:
                case ObjectExchangeOpcode.DatabaseFullFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.DatabaseError,
                        ObjectExchangeResources.Error_DatabaseFull);

                case ObjectExchangeOpcode.DatabaseLocked:
                case ObjectExchangeOpcode.DatabaseLockedFinal:
                    throw new ObjectExchangeException(
                        ObjectExchangeErrorType.DatabaseError,
                        ObjectExchangeResources.Error_DatabaseLocked);
            }
        }

        #endregion
    }
}